<?php

App::uses('CrudController', 'Controller');
App::uses('Line', 'Model');
App::uses('UserLine', 'Model');
App::uses('Validation', 'Utility');
App::uses('Categorization', 'Model');
App::uses('LogCertification', 'Model');

class AbilitiesController extends AppController
{

    public function beforeFilter()
    {
        $this->Security->validatePost = false;
        $this->Security->csrfCheck = false;
        parent::beforeFilter();
    }

    public function admin($lineId, $teamId, $userId = 0)
    {
        $this->request->allowMethod('get');
        $this->loadModel('Workstation');
        $this->loadModel('Line');
        $this->loadModel('Area');
        $this->loadModel('Moe');
        $this->loadModel('AbilityConfig');
        $this->loadModel('Categorization');
        $permissions = $this->getPermissionsCertifications();
        $categories = $this->Categorization->getEnabledByLine($lineId);
        $categories = $this->processLevels($categories);
        $appBosch = $this->ejemplo($lineId);
        $appBosch->categories = $categories;
        $appBosch->lineId = $lineId;
        $appBosch->teamId = $teamId;
        $appBosch->userId = $userId;
        $appBosch->hd = $this->AbilityConfig->getData();
        $appBosch->hd = $appBosch->hd[0];
        $appBosch->fecha = $appBosch->hd['emision_date'];
        $appBosch->jsPermissions = $permissions->toArray();
        $appBosch->hd['revision_date'] = date_format(new DateTime($appBosch->hd['revision_date']), 'd.M.Y');
        $appBosch->hd['emision_date'] = date_format(new DateTime($appBosch->hd['emision_date']), 'd.M.Y');
        $this->set('appBosch', $appBosch);
    }

    private function processLevels($levels)
    {
        $levelsWithKey = array();
        foreach ($levels as $level) {
            $levelsWithKey[$level['id']] = $level;
        }
        return $levelsWithKey;
    }

    private function ejemplo($lineId)
    {
        $this->Line->id = $lineId;
        $line = $this->Line->read();
        $this->Area->id = $line['Line']['area_id'];
        $area = $this->Area->read();
        $this->Moe->id = $area['Area']['moe_id'];
        $moe = $this->Moe->read();
        $workstations = $this->Workstation->getEnabledByLineForMh($lineId);
        $appBosch = new stdClass();
        $this->loadModel('User');
        $appBosch->description = array($moe['Moe']['name'], $area['Area']['name'], $line['Line']['name']);
        $appBosch->description = array_unique($appBosch->description);
        $appBosch->description = implode('-', $appBosch->description);
        $appBosch->moe = $moe['Moe']['name'];
        $appBosch->linea = $line['Line']['name'];
        $appBosch->workstations = $workstations;
        $appBosch->colDyn = $workstations;
        $appBosch->fields = array();
        $msgDestroyCertification = __('Eliminar certificación');
        $ws = array();
        foreach ($workstations as $workstation) {
            $ws[$workstation['id']] = $workstation;
        }
        $appBosch->workstations = $ws;
        foreach ($appBosch->colDyn as &$op) {
            $op['field'] = 'status' . $op['num'];
            $appBosch->fields[$op['field']] = array('type' => 'date');
            $op['title'] = $op['name'];
            $op['values'] = Certification::getTypes();
            $op['aggregates'] = array('sum');
            $op['width'] = 51;
            $op['filterable'] = true;
            $workstation = 'w' . $op['num'];
            $txtHeader = $op['name'];
            $op['headerTemplate'] = '<div title="' . $txtHeader . '"  class="imgWorkstation"><img src="../../../../PHP_TEMP/Workstations/' . $op['id'] . '.png"/></div>
                                     <div title="' . $txtHeader . '"  class="imgWorkstationP"><img src="../../../../PHP_TEMP/Workstations/' . $op['id'] . 'B.png"/></div>';
            $certificationId = 'c' . $op['num'];
            $ss = 's' . $op['num'];
            $date = 'd' . $op['num'];
            //$life = 'd' . $op['num'];
            $wnd = 'wnd' . $op['num'];
            $workstationDescription = $op['name'];
            $msg1 = __('Esta certificación está por caducar');
            $op['template'] = ""
                . "#if(typeof $certificationId === 'undefined'){#"
                . "    <div data-user='#=ui#' data-workstation='#=$workstation#' title='#=un# - $workstationDescription' class='uncertification'>"
                . "    </div>"
                . "#} else {"
                . "var success = getSuccess($ss);"
                . "var training = getTraining($ss);"
                . "var date = new Date($date);"
                . "#"
                . "<div data-level='#=l#' data-workstation='#=$workstation#' title='#=un# - $workstationDescription' class='certification' data-training='#=training#' data-success='#=success#'>"
                . "<div data-id='#=$certificationId#' data-user='#=ui#' data-workstation='#=$workstation#' data-level='#=l#' data-success='#=success#' class='icon'>"
                . "#if(success=='1'){#"
                . "<i class='fa level #=getIcon(l)#' style='color:#=getColor(l)#;'></i>"
                . "#}#"
                . "#if(training =='1'){#"
                . "    <i class='fa level fa-square'></i>"
                . "    <div class='date' title='Fin del proceso de certificación: #=kendo.toString(date, 'D')#'>"
                . "        <span class='longDate'>#=kendo.toString(date, 'd')#</span>"
                . "        <span class='shortDate'>#=kendo.toString(date, 'dd/MM/yy')#</span>"
                . "    </div>"
                . '#}#'
                . "#if(success=='1'){#"
                . "    <div class='date' title='Certificación caduca: #=kendo.toString(date, 'D')#'>"
                . "        <span class='longDate'>#=kendo.toString(date, 'd')#</span>"
                . "        <span class='shortDate'>#=kendo.toString(date, 'dd/MM/yy')#</span>"
                . "    </div>"
                . "#}#"
                . "</div>"
                . " #if($certificationId !== null && appBosch.jsPermissions.crud.destroy === true && (training =='1' || success == '1')) {#"
                . "     <i data-id='#=$certificationId#' class='fa fa-times' title='$msgDestroyCertification'></i>"
                . " #}#"
                . "</div>"
                . "#}#";
        }
        return $appBosch;
    }

    /**
     * AJAX
     * Abilities/admin
     * @param string $teamId UUID
     * @return array
     */
    public function read($teamId, $lineId, $userId = 0)
    {
        $this->request->allowMethod('get');
        $certifications = false;
        if ($this->request->is('ajax') === true) {
            $params = $this->request->query;
            $certifications = $this->getCertifications($teamId, $lineId, $userId, $params);
        }
        $this->set(array('records' => $certifications, '_serialize' => 'records'));
        $this->viewClass = 'Json';
    }

    private function getCertifications($teamId, $lineId, $userId, $params)
    {
        if (Validation::uuid($teamId) === true) {
            return $this->getByTeam($teamId, $lineId, $params);
        } else {
            return $this->getByUser($userId, $lineId);
        }
    }

    private function getByTeam($teamId, $lineId, $params)
    {
        $this->loadModel('Team');
        $this->loadModel('Categorization');
        $certifications = $this->Team->getMhForTeam($teamId, $lineId);
        $result = array();
        foreach ($certifications as $key => &$certification) {
            if (isset($result[$certification['ui']]) === false) {
                $result[$certification['ui']] = $certification;
            }
            $name = $certification['workstationName'];
            $result[$certification['ui']]['w' . $name] = $certification['workstationId'];
            if ($certification['certificationId'] !== null) {
                $result[$certification['ui']]['c' . $name] = $certification['certificationId'];
                $result[$certification['ui']]['s' . $name] = ($certification['certificationSuccess'] << 1) | $certification['certificationTraining'];
                $result[$certification['ui']]['d' . $name] = str_replace('-', '/', $certification['certificationEnd']);
                if ($certification['certificationSuccess'] == Certification::SUCCESS_OK) {
                    $result[$certification['ui']]['d' . $name] = str_replace('-', '/', $certification['certificationLife']);
                }
                $result[$certification['ui']]['wnd' . $name] = (int)$certification['workstationNotificationDays'];
                $result[$certification['ui']]['m' . $name] = (int)$certification['certificationMigrated'];
            }
            unset($result[$certification['ui']]['certificationId']);
            unset($result[$certification['ui']]['certificationSuccess']);
            unset($result[$certification['ui']]['certificationTraining']);
            unset($result[$certification['ui']]['certificationLock']);
            unset($result[$certification['ui']]['certificationLockDate']);
            unset($result[$certification['ui']]['certificationEnd']);
            unset($result[$certification['ui']]['certificationLife']);
            unset($result[$certification['ui']]['workstationId']);
            unset($result[$certification['ui']]['workstationName']);
            unset($result[$certification['ui']]['workstationNotificationDays']);
            unset($result[$certification['ui']]['certificationStart']);
            unset($result[$certification['ui']]['certificationStatus']);
            unset($result[$certification['ui']]['certificationMigrated']);
        }
        usort($result, function ($a, $b) {
            return $a['unm'] > $b['unm'];
        });
        return array(
            'data' => $result,
            'total' => count($result));
    }

    private function getByUser($userId, $lineId)
    {
        $this->loadModel('User');
        $this->loadModel('Categorization');
        $certifications = $this->User->getMhByUser($userId, $lineId);
        $categories = $this->Categorization->getEnabledByLine($lineId);
        $result = array();
        foreach ($certifications as $key => &$certification) {
            if (isset($result[$certification['userId']]) === false) {
                $result[$certification['userId']] = $certification;
            }
            $name = $certification['workstationName'];
            $status = null;
            if ($certification['certificationId'] === null) {
                $status = Certification::STATUS_UNCERTIFIED;
            }
            if ($certification['certificationLock'] == Certification::LOCK_ON) {
                $status = Certification::STATUS_LOCK;
            } else {
                if ($certification['certificationSuccess'] == Certification::SUCCESS_OK) {
                    $status = Certification::STATUS_CERTIFIED;
                } else {
                    if ($certification['certificationTraining'] == Certification::TRAINING_OK) {
                        $status = Certification::STATUS_TRAINING;
                    }
                }
            }
            $result[$certification['userId']]['target'] = $this->calculateTarget($categories, $certification['level'], $certification['nCertifications']);
            $result[$certification['userId']]['status' . $name] = '' . $status;
            $result[$certification['userId']]['o' . $name] = $certification['workstationOptional'];
            $result[$certification['userId']]['c' . $name] = $certification['certificationId'];
            $result[$certification['userId']]['s' . $name] = $certification['certificationSuccess'];
            $result[$certification['userId']]['t' . $name] = $certification['certificationTraining'];
            $result[$certification['userId']]['lo' . $name] = $certification['certificationLock'];
            $result[$certification['userId']]['loD' . $name] = $certification['certificationLockDate'];
            $result[$certification['userId']]['d' . $name] = str_replace('-', '/', $certification['certificationEnd']);
            $result[$certification['userId']]['l' . $name] = str_replace('-', '/', $certification['certificationLife']);
            $result[$certification['userId']]['w' . $name] = $certification['workstationId'];
            $result[$certification['userId']]['wn' . $name] = $certification['workstationName'];
            $result[$certification['userId']]['wnd' . $name] = $certification['workstationNotificationDays'];
            $result[$certification['userId']]['n' . $name] = $certification['workstationName'];
            $result[$certification['userId']]['i' . $name] = $certification['icon'];
            $result[$certification['userId']]['cc' . $name] = $certification['colour'];
            $result[$certification['userId']]['cs' . $name] = $certification['certificationStatus'];
        }
        return array_values($result);
    }

    private function calculateTarget($categories, $categoryId, $numCertifications)
    {
        $targetTxt = null;
        $targetColor = null;
        $minCertifications = 0;
        $targetCertifications = 0;
        foreach ($categories as $category) {
            if ($category['id'] == $categoryId) {
                $targetTxt = $category['name'];
                $minCertifications = $category['certifications'];
                $targetColor = $category['colour'];
                continue;
            }
            if ($targetTxt !== null) {
                $targetTxt = $category['name'];
                $targetCertifications = $category['certifications'];
                $targetColor = $category['colour'];
                break;
            }
        }
        $target = array(
            'progress' => ($targetCertifications - $minCertifications) == 0 ? 0 : ($numCertifications - $minCertifications) / ($targetCertifications - $minCertifications),
            'name' => $targetTxt,
            'colour' => $targetColor,
        );
        if ($target['progress'] > 1) {
            $target['progress'] = 1;
        }
        if ($target['progress'] < 0) {
            $target['progress'] = 0;
        }
        return $target;
    }

    public function createCertification()
    {
        $this->request->allowMethod('get');
        $userSessionId = $this->Auth->user('id');
        $result = false;
        if ($this->request->is('ajax') === true) {
            $permissions = $this->getPermissionsCertifications();
            if ($permissions->haveCreatePermission() === true) {
                $this->loadModel('Certification');
                $this->loadModel('Workstation');
                $data = $this->request->query;
                if (isset($data['uId']) && isset($data['wId']) && isset($data['cStart'])) {
                    $uId = $data['uId'];
                    $wId = $data['wId'];
                    if (Validation::uuid($uId) && Validation::uuid($wId)) {
                        try {
                            $cStart = DateTime::createFromFormat('d/m/Y', $data['cStart'], new DateTimeZone('America/Mexico_City'));
                            $cEnd = DateTime::createFromFormat('d/m/Y', $data['cEnd'], new DateTimeZone('America/Mexico_City'));
                            $dataCertification = array(
                                'user_id' => $uId,
                                'workstation_id' => $wId,
                                'start' => $cStart->format('Y-m-d'),
                                'end' => $cEnd->format('Y-m-d'),
                                'life' => null,
                                'success' => Certification::SUCCESS_NOK,
                                'training' => Certification::TRAINING_OK,
                            );
                            $certification = $this->Certification->save($dataCertification);
                            $this->loadModel('LogCertification');
                            $this->LogCertification->addCreateLog($userSessionId, $certification['Certification']);
                            $result = true;
                        } catch (Exception $exc) {
                            throw $exc;
                        }
                    }
                }
            }
        }
        $this->set(array('success' => $result, '_serialize' => 'success'));
        $this->viewClass = 'Json';
    }

    public function saveCertification()
    {
        $this->request->allowMethod('get');
        $result = false;
        $this->loadModel('Certification');
        $this->loadModel('CertificationDetail');
        $this->loadModel('Link');
        $this->loadModel('WorkstationConfig');
        $data = $this->request->query;
        if (isset($data['uId']) && isset($data['cId']) && isset($data['wId'])) {
            $cId = $data['cId'];
            $uId = $data['uId'];
            $wId = $data['wId'];
            unset($data['uId']);
            unset($data['wId']);
            if ($this->isSuccessAndMigrated($cId) === false) {
                if (Validation::uuid($uId) && Validation::uuid($wId)) {
                    try {
                        $this->saveDetails($cId, $data['details']);
                        $result = true;
                    } catch (Exception $exc) {
                        throw $exc;
                    }
                }
            }
        }
        $this->set(array('records' => $result, '_serialize' => 'records'));
        $this->viewClass = 'Json';
    }

    /**
     * Verificamos si es una certificacion exitosa y migrada.
     * Las certificaciones exitosas y migradas no se pueden modificar
     * @param $cId
     * @return bool
     */
    private function isSuccessAndMigrated($cId)
    {
        $this->Certification->id = $cId;
        $certificationRecord = $this->Certification->read();
        $this->Certification->clear();
        $certification = $certificationRecord['Certification'];
        return $certification['success'] === Certification::SUCCESS_OK && $certification['migrated'] === Certification::MIGRATED_ON;
    }

    /**
     * Guardamos los records en certifications_details
     * @param string $certificationSourceId UUID
     * @param array $workstationConfigs Arreglo con los detalles de la certificación
     */
    private function saveDetails($certificationSourceId, $workstationConfigs)
    {
        foreach ($workstationConfigs as $workstationConfigSourceId => $detail) {
            $data = array(
                'workstation_config_id' => $workstationConfigSourceId,
                'certification_id' => $certificationSourceId,
                'qualification' => null,
                'certification_date' => null,
            );
            $this->certificationDetailId($data, $detail['id']);
            if (isset($detail['date']) === true && isset($detail['qualification']) === true) {
                $date = trim($detail['date']);
                $qualification = trim($detail['qualification']);
                if ($date !== '' && $qualification !== '') {
                    $this->certificationDetailDate($data, $date);
                    $this->certificationDetailQualification($data, $qualification);
                    $certificationDetailSource = $this->CertificationDetail->save($data);
                    $this->CertificationDetail->clear();
                    /**
                     * Verificamos si el detalle de la certificacion lanza detalles de
                     * certificaciones dependientes.
                     */
                    //$this->propagation($userId, $certificationDetailSource['CertificationDetail']);
                }
            }
        }
    }

    private function certificationDetailId(&$data, $detailId)
    {
        if ($detailId !== '') {
            $data['id'] = trim($detailId);
        }
    }

    private function certificationDetailDate(&$data, $date)
    {
        if ($date !== '') {
            $date = DateTime::createFromFormat('d/m/Y', $date, new DateTimeZone('America/Mexico_City'));
            $data['certification_date'] = $date->format('Y-m-d');
        }
    }

    private function certificationDetailQualification(&$data, $qualification)
    {
        if ($qualification !== '') {
            $data['qualification'] = trim($qualification);
        }
    }

    public function user($lineId, $teamId, $userId = null)
    {
        $result = false;
        $this->request->allowMethod('get');
        if ($this->request->is('ajax') === true) {
            $params = $this->request->query;
            if (isset($params['certifications'])) {
                $this->loadModel('Certification');
                $this->Certification->deleteCertificationsByUserAndLine($lineId, $userId);
            }
            if (isset($params['user'])) {
                $this->loadModel('UserTeam');
                $this->UserTeam->deleteMember($teamId, $userId);
            }
            $result = true;
        }
        $this->set(array('records' => $result, '_serialize' => 'records'));
        $this->viewClass = 'Json';
    }

    /**
     * AJAX invocada desde la matriz de multihabilidades
     */
    public function destroyCertification()
    {
        $this->request->allowMethod('get');
        $success = false;
        if ($this->request->is('ajax') === true) {
            $userSessionId = $this->Auth->user('id');
            $this->loadModel('Certification');
            $this->loadModel('LogCertification');
            $certificationId = $this->request->query['cId'];
            $comment = $this->request->query['c'];
            $this->Certification->id = $certificationId;
            $certification = $this->Certification->read();
            $data = $certification['Certification'];
            $data['status'] = Certification::STATUS_DISABLED;
            $this->Certification->save($data);
            $this->LogCertification->addDestroyLog($userSessionId, $comment, $data);
            $success = true;
        }
        $this->set(array('success' => $success, '_serialize' => 'success'));
        $this->viewClass = 'Json';
    }

    /**
     *
     * @param string $workstationConfigSourceId UUID workstations_configs
     */
    private function propagation($userId, $certificationDetailSource)
    {
        $certificationSourceId = $certificationDetailSource['certification_id'];
        $certificationDetailSourceId = $certificationDetailSource['id'];
        $workstationConfigSourceId = $certificationDetailSource['workstation_config_id'];
        /**
         * Leemos la certificacion que desato la propagacion. Esta certificacion
         * siempre existe.
         */
        $this->Certification->id = $certificationSourceId;
        $certificationSource = $this->Certification->read();
        /**
         * Obtenemos todos los detalles de certificaciones que dependen de este
         * detalle de certificacion
         */
        $destinations = $this->Link->getByDestination($workstationConfigSourceId);
        foreach ($destinations as $workstationConfigSourceId) {
            $this->WorkstationConfig->id = $workstationConfigSourceId['source'];
            $workstationConfig = $this->WorkstationConfig->read();
            $this->WorkstationConfig->clear();
            $workstationId = $workstationConfig['WorkstationConfig']['workstation_id'];
            $qualificationAndDate = $this->Link->getPropagation($userId, $workstationConfigSourceId['source']);
            $qualification = $qualificationAndDate[0]['qualification'];
            $certificationDate = $qualificationAndDate[0]['certification_date'];
            $certification = $this->Certification->getEnabledByUserAndWorkstation($userId, $workstationId);
            if (isset($certification['Certification']) === false) {
                $newCertificationId = String::uuid();
                $dataCertification = array(
                    'id' => $newCertificationId,
                    'user_id' => $userId,
                    'workstation_id' => $workstationId,
                    'start' => $certificationSource['Certification']['start'],
                    'end' => $certificationSource['Certification']['end'],
                    'life' => $certificationSource['Certification']['life'],
                    'success' => Certification::SUCCESS_NOK,
                    'training' => Certification::TRAINING_NOK,
                );
                $this->Certification->save($dataCertification);
                $this->createDetails($workstationId, $workstationConfigSourceId['source'], $certificationSourceId, $certificationDetailSourceId, $newCertificationId, $qualification, $certificationDate);
            } else {
                $certificationSourceId = $certification['Certification']['id'];
                $workstationConfigId = $workstationConfigSourceId['source'];
                $this->CertificationDetail->updateByCertificationAndWorkstationConfig($certificationSourceId, $workstationConfigId, $certificationDetailSourceId, $qualification, $certificationDate);
            }
        }
    }

    public function createDetails($workstationId, $workstationConfigId, $certificationSourceId, $certificationDetailSourceId, $certificationId, $qualification, $certificationDate)
    {
        $workstationsConfigs = $this->WorkstationConfig->getEnabledByWorkstation($workstationId);
        foreach ($workstationsConfigs as $workstationConfig) {
            $dataCertificationDetail = array(
                'workstation_config_id' => $workstationConfig['id'],
                'certification_id' => $certificationId,
                'qualification' => $workstationConfig['id'] != $workstationConfigId ? null : $qualification,
                'certification_date' => $workstationConfig['id'] != $workstationConfigId ? null : $certificationDate,
                'source' => $certificationDetailSourceId,
            );
            $this->CertificationDetail->save($dataCertificationDetail);
            $this->CertificationDetail->clear();
        }
    }

}
